/***************************************************************
                       searchmarker.c
written by IL
edited by CAS
******************************************************************/
#include "fpp.h"
#include <ctype.h>
#include <string.h>

extern int PRTMESS;
extern void lowerstring();
extern BOOL strcasestr_priv(); //WMN: name changed for mac build

int comparedates(struct mytime *cmpdate,struct mytime *date);
void searchpick(int box, float x, float y);

/********************************************************
             DEF: markersearch() only called in getlist
*********************************************************/
void markersearch()
{
  struct list *p=NULL;
  int i,max; 
  BOOL first;

  max = arrayMax(markerdata);
  first = TRUE;

  for(i=0;i<max;i++){
      if(first){ 
	  listroot  = (struct list *)messalloc((sizeof(struct list)));	
	  listroot->index = i;
	  listroot->next = NULL;
	  first = FALSE;
	  p = listroot;
      }
      else{
	  p->next  = (struct list *)messalloc((sizeof(struct list)));	
	  p=p->next;
	  p->index= i;
      }
      p->next = NULL;
  }
}

void submarkersearch()
{
  struct list *p=NULL,*oldroot,*temp,*q;
  int i,j,index,len, lencl,pos; 
  char search[MARKER_SZ+2],search2[MARKER_SZ+2];
  MARKER *marker;
  BOOL found,first;

  strcpy(search,chsearchglob);
  if (search[0]=='\0' || search[0]=='\n') strcpy(search,"*");

  if (markerdata==NULL){
    if (PRTMESS) displaymess("NO marker data");
    return;
  }
  q = listroot;
  oldroot = listroot;
  listroot = NULL;

  if(strcmp(search,"*")==0){ /* if all to be found */
    found = TRUE;
    listroot = oldroot;
    displaykeyset(1);
    return;
  }
  else if(strncmp(search,"*",1)==0){          /* starts with * */
    j =0;
    for(i=1;i<MARKER_SZ;i++){ /* get the char bit */
      search[j++]=search[i];
    }
    if(strstr(search,"*")!=NULL){    /* if there is another * then format is *char* */
      first = TRUE;
      j =0;
      for(i=0;i<MARKER_SZ;i++){ /* get the char bit */
	if(search[i]!='*')
	  search2[j++]=search[i];
	else{
	  search2[j++]='\0';
	  break;
	}
      }
      lowerstring(search2);
      while(q!=NULL){
	marker = arrp(markerdata,q->index,MARKER);
	if(strcasestr_priv(marker->marker,search2) && marker->marker[0] != '!'){
	  if(first){
	    listroot  = (struct list *)messalloc((sizeof(struct list)));	
	    listroot->next = NULL;
	    p = listroot;
	    p->index = q->index;
	    first = FALSE;
	  }
	  else{
	    p->next = (struct list *)messalloc((sizeof(struct list)));	
	    p=p->next;
	    p->index = q->index;
	  }
	}	  
	q=q->next;
      }
      if(!first)
	p->next = NULL;
    }
    else{                     /* format is *char */ 
      len = strlen(search);	
      first = TRUE;
      while(q!=NULL){
	marker = arrp(markerdata,q->index,MARKER);
	lencl = strlen(marker->marker);
	found = TRUE;
	lowerstring(search);
	for(j=len;j>=0;j--){
	  if(search[j]!=tolower(marker->marker[lencl--])){
	    found = FALSE;
	    break;
	  }
	}
	if(marker->marker[0] == '!')
	  found = FALSE;
	if(found){
	  if(first){
	    listroot  = (struct list *)messalloc((sizeof(struct list)));	
	    listroot->next = NULL;
	    p = listroot;
	    p->index = q->index;
	    first = FALSE;
	  }
	  else{
	    p->next = (struct list *)messalloc((sizeof(struct list)));	
	    p=p->next;
	    p->index = q->index;
	  }
	}	  
	q=q->next;
      } /* end while */
      if(!first)
	p->next = NULL;
    }
  }
  else if (strstr(search,"*")!=NULL){   /* the format is char* */
    pos = 0;
    for(i=0;i<=MARKER_SZ;i++){
      if(search[i]=='*'){
	pos= i;
	break;
      }
    }
    if(pos == 0)
      printf("error * not found but should be ????\n");
    first = TRUE;
    while(q!=NULL){
      marker = arrp(markerdata,q->index,MARKER);
      if(strncasecmp(search,marker->marker,pos)==0){
	if(first){
	  listroot  = (struct list *)messalloc((sizeof(struct list)));	
	  listroot->next = NULL;
	  p = listroot;
	  p->index = q->index;
	  first = FALSE;
	}
	else{
	  p->next = (struct list *)messalloc((sizeof(struct list)));	
	  p=p->next;
	  p->index = q->index;
	}
      }	 
      q=q->next;
    }
    if(!first)
      p->next = NULL;
  }
  else{                  /* no special characters */
    if(fppFind(markerdata,search,&index, markerOrder)){
      listroot  = (struct list *)messalloc((sizeof(struct list)));	
      listroot->next = NULL;
      p = listroot;
      p->index = index;    
    }
    else{         
       printf("Exact match (Name=%s) not found.  Looking for substring.\n",search);
       first = TRUE;
       while(q!=NULL){
         marker = arrp(markerdata,q->index,MARKER);
         lowerstring(search);
         if(strcasestr_priv(marker->marker,search)){
	   if(first){
	     listroot  = (struct list *)messalloc((sizeof(struct list)));	
	     listroot->next = NULL;
	     p = listroot;
	     p->index = q->index;
	     first = FALSE;
	   }
	   else{
	     p->next = (struct list *)messalloc((sizeof(struct list)));	
	     p=p->next;
	     p->index = q->index;
	   }
         }
         q=q->next;
       }
       if(!first)
         p->next = NULL;
    }
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    printf("Marker search (Name=%s) failed for keyset of %d items.\n",chsearchglob, i);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
    graphPop();
  }
}

void creationdates_marker(int result,BOOL created)
/* if result = -1 then check before if result = 1 check after */
{
  int i;
  struct mytime searchdate,cmpdate,curdate;
  struct tm *curr_time;
  time_t ltime;
  char search[MARKER_SZ+2];
  BOOL first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  MARKER *marker;
  int junk1,junk2,junk3;

  strcpy(search,chsearchglob);
  if(sscanf(search,"%d/%d/%d",&searchdate.day,&searchdate.month,&searchdate.year)!=3){
    printf("The date \"%s\" is not in the correct format (dd/mm/yy hh:mm). hh:mm are optional. Try again\n",search);
    return;
  }
  if(sscanf(search,"%d/%d/%d %d:%d",&junk1,&junk2,&junk3,&searchdate.hour,&searchdate.minute)!=5){
    if(result == -1){
      searchdate.hour = 00;
      searchdate.minute = 00;
    }
    else{
      searchdate.hour = 23;
      searchdate.minute = 59;
     }
  }
  /* year of user input to the most recent occurence of that date */

  if (time(&ltime) != -1) {
    curr_time = localtime(&ltime);

    if (curr_time->tm_year > 99) {
      curdate.year = curr_time->tm_year - 100;
      curdate.month = curr_time->tm_mon+1;
      curdate.day = curr_time->tm_mday;
      curdate.hour = curr_time->tm_hour;
      curdate.minute = curr_time->tm_min;
      while (comparedates(&searchdate, &curdate)!=-1) {
        searchdate.year = searchdate.year + 100;
      }
    }
  }

  if (markerdata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;
  
  while(q!=NULL){
    marker = arrp(markerdata,q->index,MARKER);
    if(created)
      cmpdate = marker->creation_date;
    else
      cmpdate = marker->modified_date;
    if(comparedates(&searchdate,&cmpdate)==result){
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index = q->index;
      }
    }
    q=q->next;
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    if (created)
      printf("Marker search (Creation Date) failed for keyset of %d items.\n",i);
    else
      printf("Marker search (Modified Date) failed for keyset of %d items.\n", i);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

void mrk_destarandlower(char *temp)  
{
  char temp2[MARKER_SZ+2];
  int i,j,l;

  strcpy(temp2,temp);
  l = strlen(temp);
  for(i=0,j=0;i<=l;i++){
    if(temp2[i]!='*')
      temp[j++]=tolower(temp[i]);
  }
}

void mrknotremsearch()  
{
  int i;
  char search[MARKER_SZ+2];
  BOOL addit, first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  MARKER *marker;
  struct remark *rem;

  strcpy(search,chsearchglob);
  mrk_destarandlower(search);

  if (markerdata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;
  
  while(q!=NULL){
    addit=TRUE;
    marker = arrp(markerdata,q->index,MARKER);
    rem = marker->remark;
    while(rem != NULL && addit){
      if(strcasestr_priv(rem->message,search)){
         addit = FALSE;
      }
      rem = rem->next;
    }
    if(addit){
       if(first){
         listroot  = (struct list *)messalloc((sizeof(struct list)));	
         listroot->next = NULL;
	 p = listroot;
	 p->index = q->index;
	 first = FALSE;
       }
       else{
          p->next = (struct list *)messalloc((sizeof(struct list)));	
	  p=p->next;
	  p->index = q->index;
       }
    }
    q=q->next;
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    printf("Marker search (!Remark=%s) failed for keyset of %d items.\n",chsearchglob, i);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

void mrkremsearch()  
{
  int i;
  char search[MARKER_SZ+2];
  BOOL added, first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  MARKER *marker;
  struct remark *rem;

  strcpy(search,chsearchglob);
  mrk_destarandlower(search);

  if (markerdata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;
  
  while(q!=NULL){
    added=FALSE;
    marker = arrp(markerdata,q->index,MARKER);
    rem = marker->remark;
    while(rem != NULL && !added){
      if(!strcasecmp(rem->message,search)){
         added = TRUE;
         if(first){
	    listroot  = (struct list *)messalloc((sizeof(struct list)));	
	    listroot->next = NULL;
	    p = listroot;
	    p->index = q->index;
	    first = FALSE;
         }
         else{
	    p->next = (struct list *)messalloc((sizeof(struct list)));	
	    p=p->next;
	    p->index = q->index;
         }
      }
      rem=rem->next;
   }
   q=q->next;
  }
  if(listroot==NULL){
     printf("Exact match (Marker remark=%s) not found.  Looking for substring.\n",search);
     q= oldroot;
  
     while(q!=NULL){
       added=FALSE;
       marker = arrp(markerdata,q->index,MARKER);
       rem = marker->remark;
       while(rem != NULL && !added){
         if(strcasestr_priv(rem->message,search)){
            added = TRUE;
            if(first){
	       listroot  = (struct list *)messalloc((sizeof(struct list)));	
	       listroot->next = NULL;
	       p = listroot;
	       p->index = q->index;
	       first = FALSE;
            }
            else{
	       p->next = (struct list *)messalloc((sizeof(struct list)));	
	       p=p->next;
	       p->index = q->index;
            }
         }
         rem=rem->next;
      }
      q=q->next;
     }
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    printf("Marker search (Remark=%s) failed for keyset of %d items.\n",chsearchglob, i);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

void listmultiplecontigs()
{
  struct list *p=NULL,*oldroot,*temp,*q; 
  MARKER *marker;
  struct markerctgpos *pos;
  BOOL first = TRUE;
  int n, count, cnt=0;
  char search[50];
  
  if (markerdata==NULL){
    printf("NO marker data");
    return;
  }
  strcpy(search,chsearchglob);
  mrk_destarandlower(search);
  if(!sscanf(search,"%d",&n)){
     printf("%s is not an integer. Try again\n",search);
     return;
  }
  oldroot = listroot;
  listroot = NULL;

  for (q=oldroot; q!=NULL; q=q->next){
    cnt++;
    marker = arrp(markerdata,q->index,MARKER);
    count = 0;
    for (pos=marker->pos; pos!=NULL && count<=n; pos=pos->next){
      if(pos->ctg > 0) count++;
    }
    if(count > n){
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index = q->index;
      }
    }
  }
  if(listroot==NULL){
    printf("Marker search (> %d contigs) failed for keyset of %d items.\n",n,cnt);
    listroot = oldroot;
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  searchtype = SeaMultCtg;
  graphPop();
}

void listnocontigs()
{
  struct list *p=NULL,*oldroot,*temp,*q; 
  MARKER *marker;
  struct markerctgpos *pos;
  int n, count, cnt=0;
  BOOL first= TRUE;
  char search[50];

  if (markerdata==NULL){
    printf("NO marker data");
    return;
  }
  strcpy(search,chsearchglob);
  mrk_destarandlower(search);
  if(!sscanf(search,"%d",&n)){
     printf("%s is not an integer. Try again\n",search);
     return;
  }
  oldroot = listroot;
  listroot = NULL;

  for (q=oldroot; q!=NULL; q=q->next){
    cnt++;
    marker = arrp(markerdata,q->index,MARKER);
    count = 0;
    for (pos = marker->pos; pos!=NULL && count<=n; pos = pos->next){
      if(pos->ctg > 0) count++;
    }
    if(count <= n){
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index = q->index;
      }
    }
  }
  if(listroot==NULL){
    printf("Marker search (<= %d contigs) failed for keyset of %d items.",n,cnt);
    listroot = oldroot;
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  searchtype = SeaNoCtg;
  graphPop();
}

void list10clones()
{
  struct list *p=NULL,*oldroot,*temp,*q; 
  MARKER *marker;
  int n, cnt=0;
  BOOL first= TRUE;
  char search[50];

  if (markerdata==NULL){
    printf("NO marker data");
    return;
  }
  strcpy(search,chsearchglob);
  mrk_destarandlower(search);
  if(!sscanf(search,"%d",&n)){
     printf("%s is not an integer. Try again\n",search);
     return;
  }
  oldroot = listroot;
  listroot = NULL;

  for (q=oldroot; q!=NULL; q=q->next){
    cnt++;
    marker = arrp(markerdata,q->index,MARKER);
    if(marker->count > n){
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index = q->index;
      }
    }
  }
  if(listroot==NULL){
    printf("Marker search (> %d clones) failed for keyset of %d items.\n",n,cnt);
    listroot = oldroot;
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  searchtype = Sea10Clones;
  graphPop();
}
void listMarkerType()
{
  struct list *p=NULL,*oldroot,*temp,*q; 
  MARKER *marker;
  int i, cnt=0, type= -1;
  BOOL first= TRUE;
  char search[50];

  if (markerdata==NULL){
    printf("NO marker data");
    return;
  }
  strcpy(search,chsearchglob);
  mrk_destarandlower(search);
  for (i=0; i< markertypenum && type== -1; i++)
     if (strcasecmp(markertype[i],search)==0) type = i;
  if (type == -1) {
    printf("%s is not a valid marker type. (See Summary for marker types)\n",
         chsearchglob);
    return;
  }
  oldroot = listroot;
  listroot = NULL;

  for (q=oldroot; q!=NULL; q=q->next){
    cnt++;
    marker = arrp(markerdata,q->index,MARKER);
    if(marker->type == type){
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index = q->index;
      }
    }
  }
  if(listroot==NULL){
    printf("Marker search (Marker type %s) failed for keyset of %d items.\n",
                chsearchglob, cnt);
    listroot = oldroot;
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  searchtype = SeaType;
  graphPop();
}
